#!/bin/bash
# This script installs Docker offline or online, and provides various options for installation and configuration.
# supports installation on both Ubuntu and CentOS operating systems
# Usage: ./install.sh [--online|-o] [--force|-f] [--version=<version>] [--group=<group>] [--pkg-mirror=<https://xxx>][--image-mirror=<https://xxx>][--rm|--remove] [--clean|-c] [--downloadonly|-d]
# Options:
#   --online|-o: install using online method
#   --force|-f: force installation
#   --version=<version>: specify the version to be installed
#   --group=<group>: specify the group to be configured, default is root
#   --pkg-mirror=<https://xxx>: specify the pkg mirror to be used, default is https://mirrors.ustc.edu.cn
#         eg: 1, https://mirrors.ustc.edu.cn
#             2, https://mirrors.tuna.tsinghua.edu.cn
#             3, https://mirrors.aliyun.com
#             4, http://mirrors.163.com
#             5, http://mirrors.cloud.tencent.com
#   --image-mirror=<https://xxx>, specify the image mirror to be used, default is https://9zufkov1.mirror.aliyuncs.com
#         eg: 1, https://docker.mirrors.ustc.edu.cn
#             2, https://docker.mirrors.tuna.tsinghua.edu.cn
#             3, https://9zufkov1.mirror.aliyuncs.com
#             4, http://hub-mirror.c.163.com
#             5, https://mirror.ccs.tencentyun.com
#             6, https://registry.docker-cn.com
#   --rm|--remove: uninstall Docker
#   --clean|-c: remove downloaded files
#   --downloadonly|-d: only download Docker package, do not install
#   example1, download 20.10.20 pkg: 
#           ./install.sh --version=20.10.20 --force --downloadonly
#           ./install.sh --version=20.10.20 -fd
#   example2, install 20.10.20 then clean pkg: 
#          ./install.sh --version=20.10.20 --clean
#   example3, install 20.10.20 using apt or yum, and force installation: 
#          ./install.sh --version=20.10.20 -of
#   example4, install latest using apt or yum
#          ./install.sh --online, or ./install.sh -o
# Functionality:
# 0. This script supports installation on both Ubuntu and CentOS operating systems.
# 1. Specify the version to be installed TARGET_VERSION and whether to force if FORCE
# 2. Determine whether the local version current_version is >= the specified version TARGET_VERSION. If it is, do not install it. If --force is specified, force installation
# 3. Installation process:
#    1) Uninstall the local version
#    2) Call the official script https://get.docker.com to install the specified version
# 4. Configure group as the specified group, default is root
# 5. Configure the /etc/docker/daemon.json file
# 6. Configure and start the service
#
# 该脚本安装 Docker，支持在线(apt/yum)和离线安装(二进制安装)，并提供各种安装和配置选项。适用于ubuntu或者centos
# 使用方法: ./install.sh [--online|-o] [--force|-f] [--version=<version>] [--group=<group>] [--pkg-mirror=<https://xxx>][--image-mirror=<https://xxx>][--rm|--remove] [--clean|-c] [--downloadonly|-d]
# 选项:
#   --online|-o: 使用在线方法安装，即使用apt或者yum安装。不指定时，默认为使用二进制包安装，如果没有二进制包，则自动下载。
#   --force|-f: 强制安装
#   --version=<version>: 指定要安装的版本。如果指定的是在线安装，则自动获得最新版本，如果是离线安装，则默认为20.10.24
#   --group=<group>: 指定要配置的组，默认为 root
#   --pkg-mirror=<https://xxx>: 指定要使用的软件包镜像源，用于下载apt或者yum下载docker包，默认为 https://mirrors.ustc.edu.cn
#         例如: 1, https://mirrors.ustc.edu.cn
#             2, https://mirrors.tuna.tsinghua.edu.cn
#             3, https://mirrors.aliyun.com
#             4, http://mirrors.163.com
#             5, http://mirrors.cloud.tencent.com
#   --image-mirror=<https://xxx>, 指定要使用的 Docker 镜像源,用于pull docker镜像加速，默认为 https://9zufkov1.mirror.aliyuncs.com
#         例如: 1, https://docker.mirrors.ustc.edu.cn
#             2, https://docker.mirrors.tuna.tsinghua.edu.cn
#             3, https://9zufkov1.mirror.aliyuncs.com
#             4, http://hub-mirror.c.163.com
#             5, https://mirror.ccs.tencentyun.com
#             6, https://registry.docker-cn.com
#   --rm|--remove: 卸载 Docker
#   --clean|-c: 删除已下载的文件，单独指定，则为删除安装包，加上其它flag，则为安装后自动删除安装包
#   --downloadonly|-d: 仅下载 Docker包但不安装
#   示例1，下载20.10.20版本的包: 
#           ./install.sh --version=20.10.20 --force --downloadonly (-fd)
#   示例2，安装20.10.20版本，然后清理包: 
#          ./install.sh --version=20.10.20 --clean
#   示例3，使用在线方法(apt或者yum)安装20.10.20版本，并强制安装: 
#          ./install.sh --version=20.10.20 -fo
#   示例4，使用apt或者yum安装最新版本
#          ./install.sh --online 或者 ./install.sh -o
#实现功能：
#0，适用于ubuntu或者centos
#1，指定要安装的版本TARGET_VERSION，以及是否强制如果FORCE
#2，判断本地版本current_version是否>=指定版本TARGET_VERSION，如果是，则不安装，如果指定--force，则强制安装
#3，安装过程：
#     1)卸载本地版本
#     2)在线安装(--online)：调用官方脚本https://get.docker.com安装指定的版本
#     3)离线安装：下载官方的二进制包安装，然后解压安装
#4，配置group 为指定的group, 默认为root
#5，配置/etc/docker/daemon.json文件
#6，配置和启动service
TOP_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
CUR_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
PACKAGE_MANAGER=$((command -v apt-get > /dev/null && echo apt-get) \
    || (command -v yum > /dev/null && echo yum) \
    || (echo "Neither apt-get nor yum is installed, please install one of them first." && exit 1))
#package mirros & docker images mirrors
#linux软件镜像站和docker镜像加速站，可自行选取
#ustc 中科大
#DEFAULT_PKG_MIRROR=https://mirrors.ustc.edu.cn
#DEFAULT_IMG_MIRROR=https://docker.mirrors.ustc.edu.cn
#tsinghua 清华
#DEFAULT_PKG_MIRROR=https://mirrors.tuna.tsinghua.edu.cn
#DEFAULT_IMG_MIRROR=https://docker.mirrors.tuna.tsinghua.edu.cn
#aliyun 阿里云
DEFAULT_PKG_MIRROR="https://mirrors.aliyun.com"
DEFAULT_IMG_MIRROR="https://docker.m.daocloud.io"
#163 网易
#DEFAULT_PKG_MIRROR=http://mirrors.163.com
#DEFAULT_IMG_MIRROR=http://hub-mirror.c.163.com
#tecent 腾讯
#DEFAULT_PKG_MIRROR=http://mirrors.cloud.tencent.com
#DEFAULT_IMG_MIRROR=https://mirror.ccs.tencentyun.com
#docker官方的image加速站
#DEFAULT_IMG_MIRROR=https://registry.docker-cn.com

#docker.service, docker.socket官方指定的文件
set -x
GH_PROXY=${URL_githubProxy}
SERVICE_URL=${URL_docker_service:-"${GH_PROXY}https://raw.githubusercontent.com/moby/moby/master/contrib/init/systemd/docker.service"}
SOCKET_URL=${URL_docker_socket:-"${GH_PROXY}https://raw.githubusercontent.com/moby/moby/master/contrib/init/systemd/docker.socket"}
CONTAINERD_SERVICE=${URL_containerd_service:-"${GH_PROXY}https://raw.githubusercontent.com/containerd/containerd/main/containerd.service"}
set +x
#二进制包下载路径
#BINARY_URL_PATH=${URL_docker_bin:-"https://download.docker.com/linux/static/stable/$(uname -i)/docker-\${TARGET_VERSION}.tgz"}
BINARY_URL_PATH=${URL_docker_bin:-"${DEFAULT_PKG_MIRROR}/docker-ce/linux/static/stable/$(uname -i)/docker-\${TARGET_VERSION}.tgz"}

#要求源站的目录下安装包路径格式为http://x/.../x86_64/docker-${version}.tgz
DOWNLOAD_DIR=$TOP_DIR/package
DEFAULT_VERSION=20.10.24

# ======public==================================================
bash_xc="bash -xc"
VERSION_REGEX='[0-9]+(\.[0-9]+){2}'

HAS_CURL="$(command -v curl >/dev/null 2>&1 && echo true || echo false)"
HAS_WGET="$(command -v wget >/dev/null 2>&1 && echo true || echo false)"

# 检查本机的软件管理工具是用apt-get还是yum
HAS_APT="$(command -v apt-get >/dev/null 2>&1 && echo true || echo false)"
HAS_YUM="$(command -v yum >/dev/null 2>&1 && echo true || echo false)"

##include scripts##
##include end##

#usage: download_url <url> [target] 
download_url() {
  local target
  local url=$1
  local remote_file=""

  if [ $# -eq 2 ]; then
    target=$2
  elif [ $# -eq 1 ]; then 
    target=${1##*/}
  else
    echo "cmd err, usage: download_url <url> [target]"
    return 1
  fi
  if [ ! -f "$target" ] || ${FORCE} ; then
    if $HAS_CURL; then
      $bash_xc "curl -fsSL $url -o $target"
      if [ $? -ne 0 ]; then
        echo "curl or wget failed"
        return 3
      fi
    elif $HAS_WGET; then
      $bash_xc "wget -q $url -O $target"
      if [ $? -ne 0 ]; then
        echo "curl or wget failed"
        return 3
      fi
    fi
    echo "get $(basename $target) successfully"
    return 0
  else
    echo "do not get $(basename $url): file exist or force=${FORCE} "
    return 0
  fi
  return 0
}

download_url_until_succeed() {
  local target
  local url=$1

  if [ $# -eq 2 ]; then
    target=$2
  elif [ $# -eq 1 ]; then 
    target=${1##*/}
  else
    echo "cmd err, usage: download_url <url> [target]"
    return 1
  fi
  echo "download $url $target"

  while ! download_url $url $target; do
    sleep 5
  done
}


# Waiting for apt lock
wait_for_apt_dailyupdate_lock() {
    echo -n "check apt lock "
    while lsof /var/lib/apt/lists/lock >/dev/null 2>&1; do echo -n "." && sleep 5 ; done
    echo "OK"
}

# Remove any lock files that may be preventing package manager from running.
# 删除可能阻止包管理器运行的任何锁定文件
clean_locks() {
    if [ "$PACKAGE_MANAGER" == "apt-get" ]; then
        rm -rf /var/lib/dpkg/lock
        rm -rf /var/lib/dpkg/lock-frontend
        rm -rf /var/cache/apt/archives/lock
        wait_for_apt_dailyupdate_lock
    elif [ "$PACKAGE_MANAGER" == "yum" ]; then
        rm -rf /var/run/yum.pid
        rm -rf /var/run/yum.pid.old
        # rm -rf /var/cache/yum/*
    fi
}

# check if the current version is less than the target version.
# 检查当前版本是否小于目标版本。
check_version_lt() {
    test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" != "$1"
}

# check if the current version is greater than or equal to the target version.
# 检查当前版本是否大于或等于目标版本。
check_version_ge() {
    test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"
}

# get the latest version of Docker.
# 从软件源获取 Docker包 的最新的版本号。
get_latest_version() {
    if [ "$PACKAGE_MANAGER" == "apt-get" ]; then
        echo $(apt-cache madison docker-ce | head -1 | grep -oP "$VERSION_REGEX")
    elif [ "$PACKAGE_MANAGER" == "yum" ]; then
        echo $(yum list docker-ce --showduplicates | grep -oP "$VERSION_REGEX" | sort -rV | head -1)
    fi
}

get_default_version() {
    if $ONLINE; then
        echo $(get_latest_version)
    else
        echo "$DEFAULT_VERSION"
    fi
}

# Check if docker is installed and if it needs to be upgraded
# 判断docker是否需要安装: 返回0表示成功，非0表示不成功。
docker_needs_installation() {
    if [ -x "$(command -v docker)" ]; then
        CURRENT_VERSION=$(docker version --format '{{.Server.Version}}')
        #echo "Current version: $current_version, target version: $TARGET_VERSION"
        if [ -z "$TARGET_VERSION" ] && [ "$FORCE" = "false" ]; then
            echo "Current version is $CURRENT_VERSION, use '--force=true' or '--verion=<version> to install as desired"
            return 1
        elif check_version_ge "$CURRENT_VERSION" "$TARGET_VERSION" && [ "$FORCE" != "true" ]; then
            echo "Current version ($CURRENT_VERSION) >= target version($TARGET_VERSION), and force=$FORCE; no need to install"
            return 1
        fi
    fi
    return 0
}

# Remove all Docker related files and services
# 删除docker所有的文件
remove_docker() {
    set -x
    systemctl stop docker > /dev/null 2>&1
    systemctl stop containerd > /dev/null 2>&1
    systemctl stop docker.socket > /dev/null 2>&1
    rm -rf /usr/bin/docker*
    rm -rf /usr/bin/containerd*
    rm -rf /etc/docker
    rm -rf /etc/containerd
    #rm -rf /etc/docker/daemon.json
    rm -rf /etc/systemd/system/docker.socket
    rm -rf /etc/systemd/system/docker.service
    rm -rf /etc/systemd/system/containerd.service
    #docker数据可能有些没有备份
    #rm -rf /var/lib/docker > /dev/null 2>&1
    set +x
}

# deletes the old version of Docker.
# 删除旧版本的 Docker。
delete_old_version() {
    if [ -z "$CURRENT_VERSION" ]; then
        if [ -x "$(command -v docker)" ]; then
            CURRENT_VERSION=$(docker version --format '{{.Server.Version}}')
        else
            echo "Docker is not installed or start failed"
            #return
        fi
    fi
    echo "Delete version $CURRENT_VERSION ..."

    clean_locks
    systemctl stop docker > /dev/null 2>&1
    systemctl stop containerd > /dev/null 2>&1
    systemctl stop docker.socket > /dev/null 2>&1
    if [ "$PACKAGE_MANAGER" == "apt-get" ]; then
        local pkgs=$(dpkg -l | grep -E 'docker|containerd' | awk '{print $2}')
        if [ -n "$pkgs" ] ; then
            set -x
            apt-get remove -y $pkgs > /dev/null 2>&1
            #apt remove -y docker-ce docker-ce-cli docker-compose docker-engine docker.io containerd.io runc
            apt-get autoremove -y > /dev/null
            apt-get autoclean -y > /dev/null
            set +x
        fi
    elif [ "$PACKAGE_MANAGER" == "yum" ]; then
        local pkgs=$(rpm -qa | grep -E 'docker|containerd' | awk '{print $1}')
        if [ -n "$pkgs" ] ; then
            set -x
            yum remove -y $pkgs > /dev/null 2>&1
            yum autoremove -y > /dev/null
            yum clean all > /dev/null
            set +x
        fi
    fi
    [ "$GROUP" == "docker" ] && groupdel docker > /dev/null 2>&1
    remove_docker
}

# set the user group.
# 设置用户组。
set_user_group() {
    groupadd -f $GROUP
    usermod -aG $GROUP $USER
    local sock_file=/lib/systemd/system/docker.socket
    if [ ! -f $sock_file ]; then
        if [ -f /usr/lib/systemd/system/docker.socket ]; then
            sock_file=/usr/lib/systemd/system/docker.socket
        elif [ -f /etc/systemd/system/docker.socket ]; then
            sock_file=/etc/systemd/system/docker.socket
        fi
    fi
    sed -i "s/SocketGroup=.*/SocketGroup=$GROUP/" $sock_file
}

get_cgroupdriver() {
  local plat=$(uname -m)
  case $plat in
    x86_64|aarch64) echo "systemd" ;;
    mips64el|mips64le|mips64) echo "cgroupfs" ;;
    *) echo "systemd" ;;
  esac
}

# set the cgroup driver.
# 设置 cgroup 驱动程序。
cgroup_driver_set() {
    local cgroups=$(get_cgroupdriver)
    if grep -q "native.cgroupdriver" /etc/docker/daemon.json; then
        sed -i "s/native.cgroupdriver=[^\"]*/native.cgroupdriver=$cgroups/" /etc/docker/daemon.json
    else
        sed -i "s/^}/  \"exec-opts\":  [\"native.cgroupdriver=$cgroups\"]\n}/"  /etc/docker/daemon.json
    fi
}

# add an array to a YAML file.
# 将数组添加到 YAML 文件中。
add_array_to_yaml() {
    local file=$1
    local yq_path=$2
    local data=$3
    local new=$(echo "[\"$data\"]" | sed 's/,/\",\"/g')
    yq -i "$yq_path += $new | $yq_path |= unique"  -o json $file
}

# create the daemon.json file.
# 创建 daemon.json 文件。
create_daemon_json() {
    mkdir -p /etc/docker 
    cat > /etc/docker/daemon.json <<-EOF
{
  "data-root": "/var/lib/docker",
  "exec-opts": [
    "native.cgroupdriver=systemd"
  ],
  "registry-mirrors": [
    "$IMG_MIRROR"
  ]
}
EOF
}
# 配置 Docker。
config_docker() {
    if [ -f /etc/docker/daemon.json ] && [ -x "$(command -v yq)" ]; then
        add_array_to_yaml /etc/docker/daemon.json .registry-mirrors $IMG_MIRROR
    else
        create_daemon_json
    fi
    cgroup_driver_set
}

#配置containerd
config_containerd() {
    mkdir -p /etc/containerd
    containerd config default >/etc/containerd/config.toml  
    local cgroups="systemd"
    case $(uname -m) in
        "mips64el"|"mips64le"|"mips64")
            cgroups="cgroupfs"
            ;;
    esac
    if [ "${cgroups}" == "systemd" ]; then
        sed -i 's/SystemdCgroup =.*/SystemdCgroup = true/g' /etc/containerd/config.toml
    fi
    sed -i '/mirrors/p;s/.*/  &/;s/mirrors/&."docker.io"/' /etc/containerd/config.toml
    sed -i '/mirrors."docker.io"/p;s/\[.*docker.io.*/  endpoint = ["https:\/\/docker.m.daocloud.io"]/' /etc/containerd/config.toml
}


add_repo() {
    if [ "$PACKAGE_MANAGER" == "apt-get" ]; then
        wait_for_apt_dailyupdate_lock
        echo "add source: add-apt-repository ..."
        apt-get install -y software-properties-common > /dev/null 2>&1
        if [ ! -f /etc/apt/sources.list ]; then
            touch /etc/apt/sources.list
        fi		
	    mkdir -p /etc/apt/sources.list.d
	    local arch=$(dpkg --print-architecture)
	    #local company=$(echo $MIRROR | grep -oP "(?<=\/\/)[^\/]+")
	    #sed -i "/$company/s/^/#/" /etc/apt/sources.list
	    sed -i "s/^/#/g" /etc/apt/sources.list
	    for repo in bionic bionic-backports bionic-proposed bionic-security bionic-updates; do
	        bash -xc "add-apt-repository \"deb [arch=$arch] $PKG_MIRROR/ubuntu $repo main restricted universe multiverse\" > /dev/null"
        done
        echo "update packages: apt-get update ... "
        apt-get update -qq > /dev/null 2>&1
    elif [ "$PACKAGE_MANAGER" == "yum" ]; then
        echo "add source: yum-config-manager ..."
        yum install -y yum-utils > /dev/null 2>&1
        yum-config-manager --add-repo "$PKG_MIRROR/docker-ce/linux/centos/docker-ce.repo"
        echo "update packages: yum makecache ... "
        yum makecache -y > /dev/null 2>&1
    fi
}
# install Docker online.
# 在线安装 Docker。
install_docker_online() {
    local count=0
    clean_locks
    if [ ! -f "$CUR_DIR/get-docker.sh" ]; then
        bash -xc "curl -fsSL https://get.docker.com -o $CUR_DIR/get-docker.sh"
        chmod +x $CUR_DIR/get-docker.sh
    fi
    set -x
    echo -ne '\n' | bash -c "VERSION=$TARGET_VERSION $CUR_DIR/get-docker.sh --mirror Aliyun"
    set_user_group
    config_docker
    config_containerd
    #systemctl unmask containerd
    #systemctl unmask docker
    systemctl enable docker
    systemctl enable containerd
    systemctl daemon-reload
    systemctl restart containerd > /dev/null 2>&1
    systemctl restart docker > /dev/null 2>&1
    set +x
    while true; do
      st=$(systemctl is-active docker)
      case $st in
          activating)
              sleep 1
              ;;
          failed)
              let count=count+2
              if [ $count -eq 30 ]; then
                  echo "timeout, start docker use cmd: systemctl restart docker"
                  break
              fi
              sleep $count
              systemctl daemon-reload
              systemctl restart docker
              ;;
          active)
              break
              ;;
      esac
    done
    systemctl status docker | head -8
    docker --version
}

install_docker_offline() {
    if [ ! -f $DOWNLOAD_DIR/$DOWNLOAD_TARGET ]; then
        download_pkg
    fi
    bash -xc "tar zxvf $DOWNLOAD_DIR/$DOWNLOAD_TARGET -C $DOWNLOAD_DIR> /dev/null "
    if [ -f  $DOWNLOAD_DIR/install.sh ]; then
        chmod +x $DOWNLOAD_DIR/install.sh
        bash $DOWNLOAD_DIR/install.sh
    elif [ -d $DOWNLOAD_DIR/docker ]; then
        set -x
        cp -rf $DOWNLOAD_DIR/docker/* /usr/bin/
        sed -i 's|ExecStart=[^ \t]*/dockerd|ExecStart=/usr/bin/dockerd|g' $DOWNLOAD_DIR/systemd/docker.service
        cp -rf $DOWNLOAD_DIR/systemd/docker.service /etc/systemd/system/
        cp -rf $DOWNLOAD_DIR/systemd/docker.socket /etc/systemd/system/
        sed -i 's|ExecStart=[^ \t]*/containerd|ExecStart=/usr/bin/containerd|g' $DOWNLOAD_DIR/systemd/containerd.service
        cp -rf $DOWNLOAD_DIR/systemd/containerd.service /etc/systemd/system/
        set_user_group
        config_docker
        config_containerd
        systemctl enable /etc/systemd/system/docker.service
        systemctl enable /etc/systemd/system/docker.socket
        systemctl enable /etc/systemd/system/containerd.service
        systemctl unmask containerd
        systemctl unmask docker
        systemctl daemon-reload
        systemctl restart containerd > /dev/null 2>&1
        systemctl restart docker > /dev/null 2>&1
        set +x
    fi    
    while true; do
        st=$(systemctl is-active docker)
        case $st in
            activating)
                sleep 1
                ;;
            failed|inactive)
                let count=count+2
                if [ $count -eq 30 ]; then
                    echo "timeout, start docker use cmd: systemctl restart docker"
                    break
                fi
                sleep $count
                systemctl daemon-reload
                systemctl restart docker
                ;;
            active)
                break
                ;;
        esac
    done
    systemctl status docker | head -8
    docker --version
}

download_pkg() {
    mkdir -p $DOWNLOAD_DIR
    local binary_url=$(eval echo ${BINARY_URL_PATH})
    download_url_until_succeed $binary_url $DOWNLOAD_DIR/$DOWNLOAD_TARGET
    mkdir -p $TOP_DIR/systemd
    mkdir -p $DOWNLOAD_DIR/systemd
    if [ ! -f $TOP_DIR/systemd/docker.service ]; then
        download_url_until_succeed $SERVICE_URL $TOP_DIR/systemd/docker.service
    fi
    cp -rf $TOP_DIR/systemd/docker.service $DOWNLOAD_DIR/systemd/docker.service

    if [ ! -f $TOP_DIR/systemd/docker.socket ] ; then
        download_url_until_succeed $SOCKET_URL $TOP_DIR/systemd/docker.socket
    fi
    cp -rf $TOP_DIR/systemd/docker.socket $DOWNLOAD_DIR/systemd/docker.socket

    if [ ! -f $TOP_DIR/systemd/containerd.service ]; then
        download_url_until_succeed $CONTAINERD_SERVICE $TOP_DIR/systemd/containerd.service
    fi
    cp -rf $TOP_DIR/systemd/containerd.service $DOWNLOAD_DIR/systemd/containerd.service
}

clean_download() {
    rm -rf $DOWNLOAD_DIR
    #rm -rf $CUR_DIR/get-docker.sh
}


function print_usage() {
    echo "Usage: $0 [--online|-o] [--force|-f] [--version=<version>] [--group=<group>] [--pkg-mirror=<https://xxx>][--image-mirror=<https://xxx>][--rm|--remove] [--clean|-c] [--downloadonly|-d]"
    echo "Options:"
    echo "  --online|-o: install using apt-get or yum(online=true), default install method is using binary(online=false)"
    echo "  --force|-f: force installation, default force=false"
    echo "  --version=<version>: specify the version to be installed, default is latest(online) or 20.10.24(apt/yum)"
    echo "  --group=<group>: specify the group to be configured, default is root"
    echo "  --pkg-mirror=<https://xxx>: specify the pkg mirror to be used, default is https://mirrors.ustc.edu.cn"
    echo "         eg: 1, https://mirrors.ustc.edu.cn"
    echo "             2, https://mirrors.tuna.tsinghua.edu.cn"
    echo "             3, https://mirrors.aliyun.com"
    echo "             4, http://mirrors.163.com"
    echo "             5, http://mirrors.cloud.tencent.com"
    echo "  --image-mirror=<https://xxx>, specify the image mirror to be used, default is https://9zufkov1.mirror.aliyuncs.com"
    echo "         eg: 1, https://docker.mirrors.ustc.edu.cn"
    echo "             2, https://docker.mirrors.tuna.tsinghua.edu.cn"
    echo "             3, https://9zufkov1.mirror.aliyuncs.com"
    echo "             4, http://hub-mirror.c.163.com"
    echo "             5, https://mirror.ccs.tencentyun.com"
    echo "             6, https://registry.docker-cn.com"
    echo "  --rm|--remove: uninstall Docker"
    echo "  --clean|-c: remove downloaded files"
    echo "  --downloadonly|-d: only download Docker package, do not install"
    echo "  example1, download 20.10.20 binary pkg: "
    echo "          ./install.sh --version=20.10.20 --force --downloadonly"
    echo "  example2, install 20.10.20 using binary pkg, and then clean binary pkg" 
    echo "         ./install.sh --version=20.10.20 --clean"
    echo "  example3, install 20.10.20 using online method(by apt or yum), and force installation:" 
    echo "         ./install.sh --version=20.10.20 -fo"
}

#
#=====================main func ==============================
start_time=`date --date='0 days ago' "+%Y-%m-%d %H:%M:%S"`
if [[ $EUID -ne 0 ]]; then
    echo "This script must be run as root"
    exit 1
fi

#清除旧版本的影响，保证command -v命令得到正确的结果
hash -r
if [ "$(systemctl is-active docker)" != "active" ]; then
    systemctl stop containerd > /dev/null 2>&1
    systemctl stop docker > /dev/null 2>&1
    systemctl stop docker.socket > /dev/null 2>&1
fi

ARGS=$#

# Parse command line arguments
while [[ $# -gt 0 ]]
do
    key="$1"
    case $key in
    --online|-o)
        ONLINE=true
        shift
        ;;
    --clean|-c)
        if [[ $ARGS -eq 1 ]]; then
            clean_download
            exit 0
        fi
        AUTOCLEAN=true
        shift
        ;;
    --downloadonly|-d)
        DOWNLOAD_ONLY=true
        shift
        ;;
    --force|-f)
        FORCE=true
        shift
        ;;
    --group=*)
        GROUP="${key#*=}"
        shift
        ;;
    --group)
        shift
        GROUP="$1"
        shift
        ;;
    --pkg-mirror=*)
        PKG_MIRROR="${key#*=}"
        shift
        ;;
    --pkg-mirror)
        shift
        PKG_MIRROR="$1"
        shift
        ;;
    --image-mirror=*)
        IMG_MIRROR="${key#*=}"
        shift
        ;;
    --image-mirror)
        shift
        IMG_MIRROR="$1"
        shift
        ;;       
    --version)
        shift
        TARGET_VERSION="${key}"
        shift
        ;;
    --version=*)
        TARGET_VERSION="${key#*=}"
        shift
        ;;    
    --help)
        print_usage
        exit 1
        ;;
    --rm|--remove)
        echo "Docker uninstall..."
        delete_old_version
        exit 1
        ;;
    -[^-]*)
        for ((i=1; i<${#key}; i++)); do
          case "${key:$i:1}" in
            o) ONLINE=true ;;
            f) FORCE=true ;;
            c) AUTOCLEAN=true ;;
            d) DOWNLOAD_ONLY=true ;;
            *) print_usage; exit 1 ;;
          esac
        done
        shift    
        ;;
    *)    # unknown option
        print_usage
        exit 1
        ;;
    esac
done

ONLINE=${ONLINE:-false}
PKG_MIRROR=${PKG_MIRROR:-$DEFAULT_PKG_MIRROR}
IMG_MIRROR=${IMG_MIRROR:-$DEFAULT_IMG_MIRROR}
FORCE=${FORCE:-false}
GROUP=${GROUP:-root}

#设置软件安装源，从而获得最新版本
if  [ -z "$TARGET_VERSION" ] || docker_needs_installation ; then
    $ONLINE && add_repo
fi
TARGET_VERSION=${TARGET_VERSION:-$(get_default_version)}
DOWNLOAD_TARGET=docker-${TARGET_VERSION}.tgz
DOWNLOAD_ONLY=${DOWNLOAD_ONLY:-false}
AUTOCLEAN=${AUTOCLEAN:-false}

#downloadUrl=${K8S_criUrl:-"http://192.168.49.15:9000/edge/components/cri/docker-${version}.tgz"}
echo "targetVersion=$TARGET_VERSION force=$FORCE online=$ONLINE"
echo "downloadonly=$DOWNLOAD_ONLY group=$GROUP pkg-mirror=$PKG_MIRROR"
if ! $ONLINE; then
    echo "binary package download url=$BINARY_URL_PATH"
fi

if $ONLINE && $DOWNLOAD_ONLY; then
    echo "Err: downloadonly used only in offline mode"
    exit 1
fi
if $DOWNLOAD_ONLY ; then
    download_pkg
    exit 0
fi

#exit
# Main script
# 检查下载软件curl 或者 wget是否具备
if ! $HAS_CURL && ! $HAS_WGET; then
  echo "Either curl or wget is required"
  exit 1
fi

if docker_needs_installation; then
    ps -ef --ppid=1 | grep -E 'containerd-shim\s' | awk '{print $2}' | xargs kill -9  > /dev/null 2>&1
    delete_old_version

    echo "Install version $TARGET_VERSION ..."
    if $ONLINE ; then
        install_docker_online
    else
        install_docker_offline
        $AUTOCLEAN && clean_download
    fi
fi

end_time=$(date --date="0 days ago" "+%Y-%m-%d %H:%M:%S")
duration=$(($(($(date +%s -d "$end_time")-$(date +%s -d "$start_time")))))
echo "install finished, start time $start_time, end time $end_time, duration $(($duration/60))'$(($duration%60))\""

